#ifndef WEBSERVER_H
#define WEBSERVER_H


#include <unordered_map>
#include <fcntl.h>       // fcntl()
#include <unistd.h>      // close()
#include <assert.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>



#include "../Log/log.h" /*Log会有一个额外的线程执行IO耗时的操作*/
#include "../POOL/sqlconnpool.h"
#include "../POOL/sqlconnRAII.h"

#include "../HTTP/httpconn.h"

#include "../MultiReactor/Epoller.h"
#include "../MultiReactor/EventLoop.h"
#include "../MultiReactor/EventLoopThreadPool.h"
#include "../MultiReactor/Acceptor.h"

class WebServer {
public:
public:
    using ThreadInitCallback = std::function<void(EventLoop *)>;

    enum Option
    {
        kNoReusePort,//不允许重用本地端口
        kReusePort,//允许重用本地端口
    };
    WebServer(
        EventLoop *loop,
        const InetAddress &listenAddr,
        const std::string &nameArg,
        int sqlPort, const char* sqlUser, const  char* sqlPwd, 
        const char* dbName, int connPoolNum, 
        int threadNum,
        bool openLog, int logLevel, int logQueSize);

    ~WebServer();

    // 设置底层subloop的个数
    void setThreadNum(int numThreads);
    /**
     * 如果没有监听, 就启动服务器(监听).
     * 多次调用没有副作用.
     * 线程安全.
     */
    void Start();
private:
 
    void newConnection(int sockfd, const InetAddress &peerAddr);
    void removeConnection(const HttpConnPtr &conn);
    void removeConnectionInLoop(const HttpConnPtr &conn);

    using ConnectionMap = std::unordered_map<std::string, HttpConnPtr>;

    EventLoop *loop_; // baseloop 用户自定义的loop

    const std::string ipPort_;
    const std::string name_;

    std::unique_ptr<Acceptor> acceptor_; // 运行在mainloop 任务就是监听新连接事件

    std::shared_ptr<EventLoopThreadPool> threadPool_; // one loop per thread

    ConnectionCallback connectionCallback_;       //有新连接时的回调
    MessageCallback messageCallback_;             // 有读写事件发生时的回调
    WriteCompleteCallback writeCompleteCallback_; // 消息发送完成后的回调

    ThreadInitCallback threadInitCallback_;     // loop线程初始化的回调
    int numThreads_;                            //线程池中线程的数量。
    std::atomic_int started_;
    int nextConnId_;
    ConnectionMap connections_;                 // 保存所有的连接

    char* srcDir_;                     // 资源的位置
};
#endif